/**
 * @param auth
 * @returns {Promise<unknown>}
 */
const isAuth = async (auth) => {
    let [err, res] = await uni.getSetting();
    if (err || res === false) return 0;
    if (!!res.authSetting[auth]) return 1;
    return (typeof res.authSetting[auth]) == 'boolean' ? -1 : 0;
};

/**
 * @param auth
 * @returns {Promise<* | boolean>}
 */
const authorize = async auth => {
    let [err, res] = await uni.authorize({scope: auth});
    if (err) return false;
    return res;
};

/**
 * @param auth
 * @returns {Promise<* | boolean>}
 */
const openSetting = async auth => {
	let [modalErr, modalRes] = await uni.showModal({
		title: '提示',
		content: '是否打开设置界面开启对应权限'
	});
	if (modalErr || !modalRes.confirm) {
		return false;
	}
	let [settingErr, settingRes] = await uni.openSetting();
	if (settingErr || settingRes === false) {
		return false;
	}
	return !!settingRes.authSetting[auth];
}

const helper = {
    /**
     * @param auth
     * @returns {Promise<unknown>}
     */
    async auth(auth) {
        let authStatus = await isAuth(auth);
        if (authStatus === 1) return true;
        if (authStatus === 0) return await authorize(auth);
        return await openSetting(auth);
    },

    /**
     * @param data
     * @returns {*}
     */
    queryEncode(data) {
        let arr = '';
        for (let key in data) {
            arr.push(`${ key }=${ data[key] }`);
        }
        return arr.join('&');
    },

    /**
     * @param data
     * @returns {{}}
     */
    queryDecode(data) {
        data = data.split('?');
        data = data.length === 1 ? data[0] : data[1];
        let arr = data.split('&'),
            json = {};
        arr.forEach(item => {
            let itemArr = item.split('=');
            json[itemArr[0]] = itemArr[1];
        });
        return json;
    },

    /**
     * @returns {*}
     */
    prevPage() {
        let page = getCurrentPages(),
            prePageIndex = page.length - 2;
        if (prePageIndex < 0) return null;
        return page[page.length - 2].$vm;
    },

    /**
     * @param mobile
     * @returns {*}
     */
    mobileHide(mobile) {
        let reg = /^(\d{3})\d{4}(\d{4})$/;
        return mobile.replace(reg, "$1****$2");
    },

    /**
     * @param idCard
     * @returns {*}
     */
    idCardHide(idCard) {
        let reg = /^(\d{2})\d{12}(\d|\X){4}$/;
        return idCard.replace(reg, "$1************$2");
    },

    /**
     * @param phone
     */
    callPhone(phone) {
        uni.makePhoneCall({
            phoneNumber: phone,
            fail() {
                uni.showToast({title: '呼叫失败', icon: 'none'});
            }
        });
    },

    /**
     * 本算法来源于简书开源代码，详见：https://www.jianshu.com/p/fdbf293d0a85
     * 全局唯一标识符（uuid，Globally Unique Identifier）,也称作 uuid(Universally Unique IDentifier)
     * 一般用于多个组件之间,给它一个唯一的标识符,或者v-for循环的时候,如果使用数组的index可能会导致更新列表出现问题
     * 最可能的情况是左滑删除item或者对某条信息流"不喜欢"并去掉它的时候,会导致组件内的数据可能出现错乱
     * v-for的时候,推荐使用后端返回的id而不是循环的index
     * @param {Number} len uuid的长度
     * @param {Boolean} firstM 将返回的首字母置为"m"
     * @param {Nubmer} radix 生成uuid的基数(意味着返回的字符串都是这个基数),2-二进制,8-八进制,10-十进制,16-十六进制
     */
    guid(len = 32, firstM = true, radix = null) {
        const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')
        const uuid = []
        radix = radix || chars.length

        if (len) {
            // 如果指定uuid长度,只是取随机的字符,0|x为位运算,能去掉x的小数位,返回整数位
            for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix]
        } else {
            let r
            // rfc4122标准要求返回的uuid中,某些位为固定的字符
            uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'
            uuid[14] = '4'

            for (let i = 0; i < 36; i++) {
                if (!uuid[i]) {
                    r = 0 | Math.random() * 16
                    uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r]
                }
            }
        }
        // 移除第一个字符,并用u替代,因为第一个字符为数值时,该guuid不能用作id或者class
        if (firstM) {
            uuid.shift()
            return `m${uuid.join('')}`
        }
        return uuid.join('')
    },

    /**
     * @param val
     * @returns {number}
     */
    toInt(val) {
        if (typeof val === 'undefined') return 0;
        return parseInt(val);
    },

    /**
     * @param val
     * @returns {string|*}
     */
    dateTimeToDate(val) {
        if (typeof val === 'undefined' || !val) return '0000-00-00';
        return val.split(' ')[0];
    },

    copy(content, success = () => {}, error = () => {}) {
        if(!content) return error('复制的内容不能为空 !')
        content = typeof content === 'string' ? content : content.toString() // 复制内容，必须字符串，数字需要转换为字符串
        /**
         * 小程序端 和 app端的复制逻辑
         */
        //#ifndef H5
        uni.setClipboardData({
            data: content,
            success: function() {
                success("复制成功~")
            },
            fail:function(){
                success("复制失败~")
            }
        });
        //#endif

        /**
         * H5端的复制逻辑
         */
        // #ifdef H5
        if (!document.queryCommandSupported('copy')) { //为了兼容有些浏览器 queryCommandSupported 的判断
            // 不支持
            error('浏览器不支持')
        }
        let textarea = document.createElement("textarea")
        textarea.value = content
        textarea.readOnly = "readOnly"
        document.body.appendChild(textarea)
        textarea.select() // 选择对象
        textarea.setSelectionRange(0, content.length) //核心
        let result = document.execCommand("copy") // 执行浏览器复制命令
        if(result){
            success("复制成功~")
        }else{
            error("复制失败，请检查h5中调用该方法的方式，是不是用户点击的方式调用的，如果不是请改为用户点击的方式触发该方法，因为h5中安全性，不能js直接调用！")
        }
        textarea.remove()
        // #endif
    },
	
	/* 图片预览基础版本 */
	imagePreview(images, index){
		/* images必须为数组 */
		uni.previewImage({
			urls: images,
			current:index,
		});
	},
	
	toPage(url){
		uni.navigateTo({
			url: url,
			fail(){
				uni.switchTab({
					url: '/pages/index/index'
				})
			}
		})
		
	},
	
	/**
	 * 获取一组经纬度中中心经纬度
	 * @param {Object} pointArray
	 */
	getCenterPoint(pointArray) {
	    let sortedLongitudeArray = pointArray.map(item => item.longitude).sort(),
			sortedLatitudeArray = pointArray.map(item => item.latitude).sort(),
			centerLongitude = ((parseFloat(sortedLongitudeArray[0]) + parseFloat(sortedLongitudeArray[sortedLongitudeArray.length - 1])) / 2).toFixed(4),
			centerLatitude = ((parseFloat(sortedLatitudeArray[0]) + parseFloat(sortedLatitudeArray[sortedLatitudeArray.length - 1])) / 2).toFixed(4);
		return {longitude: centerLongitude, latitude: centerLatitude};
	},
	
	/**
	 * 获取一组经纬度面积
	 * @param {Object} path
	 */
	computeSignedArea(path) {
		//传入path：[{latitude:,longitude:}],[{latitude:,longitude:}],[{latitude:,longitude:}]
	    let radius= 6371009;
	    let len = path.length;
	    if (len < 3) return 0;
	    let total = 0;
	    let prev = path[len - 1];
	    let prevTanLat = Math.tan(((Math.PI / 2 - prev.latitude/180*Math.PI) / 2));
	    let prevLng = (prev.longitude)/180*Math.PI;
		let polarTriangleArea = (tan1,lng1,tan2,lng2) => {
	        let deltaLng = lng1 - lng2;
	        let t = tan1 * tan2;
	        return 2 * Math.atan2(t * Math.sin(deltaLng), 1 + t * Math.cos(deltaLng));
		};
	    for (let i in path) {
	        let tanLat = Math.tan((Math.PI / 2 -
	            (path[i].latitude)/180*Math.PI) / 2);
	        let lng = (path[i].longitude)/180*Math.PI;
	        total += polarTriangleArea(tanLat, lng, prevTanLat, prevLng);
	        prevTanLat = tanLat;
	        prevLng = lng;
	    }
	    return Math.abs(total * (radius * radius));
	},
	
	
	/**
	 * 支付
	 * @param {String} provider alipay：支付宝，wxpay： 微信支付，baidu：百度收银台，appleiap：苹果应用内支付
	 * @param {Object} config	 
	 */
	async payment(provider, config) {
		let [err, res] = await uni.requestPayment({
			provider,
			orderInfo: config?.orderInfo || '',
			timeStamp: config?.timeStamp || '',
			nonceStr: config?.nonceStr || '',
			package: config?.package || '',
			signType: config?.signType || '',
			paySign: config?.paySign || ''
		});
		if (err !== null) {
			return err?.errMsg;
		}
		return true;
	},
	
	async getAudioDuration(audioUrl, callback = () => {}) {
		let context = uni.createInnerAudioContext(),
			duration = 0;
		context.src = audioUrl;
		context.volume = 0;
		context.onCanplay(() => {
			context.play();
		});
		context.onError(err => {
			console.log(err);
			context.destroy();
		});
		duration = await new Promise(resolve => {
			context.onTimeUpdate(() => {
				if (context.duration && context.duration > 0) {
					let duration = Math.ceil(context.duration);
					if (duration.toString() === 'Infinity') {
						return;
					}
					context.destroy();
					resolve(duration);
				}
			});
		});
		callback(duration);
		return duration;
	},
};

export default helper;